<template>
  <div class="app-container">
    <el-row :gutter="20" style="height: 100%">
      <!-- 会话列表 -->
      <el-col :span="6" class="conversation-sidebar">
        <el-button
          type="primary"
          @click="handleAddConversation"
          style="width: 100%; margin-bottom: 12px"
        >新建会话</el-button>

        <div class="conversation-header">历史对话：</div>

        <div class="conversation-scroll">
          <el-menu
            :default-active="String(activeConversationId)"
            class="el-menu-vertical-demo conversation-menu"
            @select="handleSelectConversation"
          >
            <el-menu-item
              v-for="item in conversationList"
              :key="item.conversationId"
              :index="String(item.conversationId)"
              :class="{ 'is-active': item.conversationId === activeConversationId }"
              @mouseenter="item.hover = true"
              @mouseleave="item.hover = false"
            >
              <div class="conversation-item-content">
                <div class="conversation-title" :title="item.title">{{ item.title || '新会话' }}</div>
                <el-dropdown
                  class="dropdown-button"
                  v-if="item.hover || dropdownVisibleId === item.conversationId"
                  trigger="click"
                  @visible-change="(visible) => handleDropdownVisibleChange(visible, item.conversationId)"
                  @command="(command) => handleDropdownCommand(command, item)"
                >
                  <span class="el-dropdown-link">
                    <el-icon><MoreFilled /></el-icon>
                  </span>
                  <template #dropdown>
                    <el-dropdown-menu>
                      <el-dropdown-item command="rename">重命名</el-dropdown-item>
                      <el-dropdown-item command="delete">删除</el-dropdown-item>
                    </el-dropdown-menu>
                  </template>
                </el-dropdown>
              </div>
            </el-menu-item>
          </el-menu>
        </div>
      </el-col>

      <!-- 聊天区域 -->
      <el-col :span="18" class="chat-area">
        <!-- 消息列表 -->
        <div class="message-list">
          <!-- AI 固定欢迎消息 -->
          <div class="message-wrapper ai-message">
            <div class="message-avatar">🤖</div>
            <div class="message-bubble">
              <strong>AI：</strong>
              <span>😊智慧农业助手已上线，欢迎咨询农业相关问题！</span><br />
            </div>
          </div>

          <!-- 动态消息 -->
          <div
            v-for="(msg, index) in messageList"
            :key="index"
            class="message-wrapper"
            :class="msg.role === 0 ? 'ai-message' : 'user-message'"
          >
            <div class="message-avatar">
              {{ msg.role === 0 ? '🤖' : (userStore.nickName?.[0] || '我') }}
            </div>

            <div class="message-bubble">
              <strong>{{ msg.role === 0 ? 'AI' : userStore.nickName }}：</strong>
              <span>{{ msg.content }}</span>
              <span
                v-if="msg.role === 0 && msg.loading"
                class="loading-wrapper"
              >
                <span class="loading-dot"></span>
              </span>
              <br />
              <small class="message-time">
                {{ msg.createdAt ? dayjs(msg.createdAt).format('YYYY-MM-DD HH:mm:ss') : '' }}
              </small>
            </div>
          </div>
        </div>

        <!-- 输入区 -->
        <div class="message-input-wrapper">
          <el-input
            type="textarea"
            v-model="newMessage"
            placeholder="请输入内容"
            :rows="3"
            class="message-input"
            @keyup.enter.native.prevent="handleSendMessage"
          />
          <el-button
            type="primary"
            class="send-button"
            @click="handleSendMessage"
            :disabled="sending || !newMessage.trim()"
          >{{ sending ? '发送中...' : '发送' }}</el-button>

        </div>
      </el-col>
    </el-row>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted } from "vue";
import { getToken } from "@/utils/auth";
import { ElMessage, ElMessageBox } from "element-plus";
import { MoreFilled } from "@element-plus/icons-vue";
import dayjs from "dayjs";
import { nextTick, watch } from "vue";
import {
  listConversations,
  addConversations,
  updateConversations,
  delConversations
} from "@/api/agriculture/znjc/conversations";


import {
  listMessages,
  addMessages,
  updateMessages
} from "@/api/agriculture/znjc/messages";

import useUserStore from "@/store/modules/user";
const userStore = useUserStore();

const conversationList = ref([]);
const messageList = ref([]); // 用ref包裹数组，确保响应式生效
const newMessage = ref("");
const activeConversationId = ref(null);
const sending = ref(false);
const defaultUserId = 1;
const dropdownVisibleId = ref(null);

let recognition = null;
const fixedMessageTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
function handleStartVoice() {
  if (!("SpeechRecognition" in window || "webkitSpeechRecognition" in window)) {
    ElMessage.error("浏览器不支持语音识别");
    return;
  }

  recognition = new (window.SpeechRecognition ||
    window.webkitSpeechRecognition)();
  recognition.lang = "zh-CN";
  recognition.interimResults = true;
  recognition.continuous = false;

  recognition.onresult = event => {
    let transcript = "";
    for (let i = event.resultIndex; i < event.results.length; i++) {
      transcript += event.results[i][0].transcript;
    }
    newMessage.value = transcript; // 识别结果实时赋值输入框
  };

  recognition.onerror = event => {
    console.error("语音识别错误:", event.error);
    ElMessage.error("语音识别出错：" + event.error);
  };

  recognition.onend = () => {
    ElMessage.success("语音识别结束");
  };

  recognition.start();
}

function formatCreatedTime(item) {
  const time = item.updatedAt || item.updateTime || item.createdAt;
  return time ? dayjs(time).format("YYYY-MM-DD HH:mm:ss") : "-";
}

function handleDropdownVisibleChange(visible, conversationId) {
  dropdownVisibleId.value = visible ? conversationId : null;
}
async function scrollToBottom() {
  await nextTick(); // 等待 DOM 更新
  const el = document.querySelector(".message-list");
  if (el) el.scrollTop = el.scrollHeight;
}
onMounted(async () => {
  if (!userStore.nickName) {
    await userStore.getInfo();
  }
  await loadConversations();
  await scrollToBottom();
});

function handleDropdownCommand(command, item) {
  if (command === "rename") {
    ElMessageBox.prompt("请输入新的会话名称", "重命名", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      inputValue: item.title,
      inputPattern: /^.{1,50}$/,
      inputErrorMessage: "会话名称不能为空，最长50字"
    }).then(async ({ value }) => {
      try {
        await updateConversations({
          conversationId: item.conversationId,
          title: value
        });
        ElMessage.success("重命名成功");
        await loadConversations();
      } catch (error) {
        ElMessage.error("重命名失败");
      }
    });
  } else if (command === "delete") {
    ElMessageBox.confirm("此操作将永久删除该会话，是否继续？", "警告", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning"
    }).then(async () => {
      try {
        await delConversations(item.conversationId);
        ElMessage.success("删除成功");
        if (activeConversationId.value === item.conversationId) {
          activeConversationId.value = null;
          messageList.value = [];
        }
        await loadConversations();
      } catch (error) {
        ElMessage.error("删除失败");
      }
    });
  }
}

async function loadConversations() {
  const res = await listConversations({
    pageNum: 1,
    pageSize: 1000
  });
  let list = res.rows || res.data || [];

  list.forEach(item => {
    const baseTime = item.updatedAt || item.updateTime || item.createdAt;
    item.localUpdateTime = baseTime ? new Date(baseTime).getTime() : 0;
    item.hover = false;
  });

  list.sort((a, b) => b.localUpdateTime - a.localUpdateTime);
  conversationList.value = list;

  if (
    activeConversationId.value === null &&
    conversationList.value.length > 0
  ) {
    activeConversationId.value = conversationList.value[0].conversationId;
    await loadMessages(activeConversationId.value, 1, true);
  }
}

async function loadMessages(conversationId, page = 1, scroll = false) {
  const res = await listMessages({
    conversationId,
    pageNum: page,
    pageSize: 100
  });
  messageList.value = res.rows || res.data || [];
  if (scroll) {
    await scrollToBottom();
  }
}

async function handleAddConversation() {
  // 判断 AI 是否正在回复，或者正在发送消息
  const aiLoading = messageList.value.some(msg => msg.role === 0 && msg.loading);
  if (aiLoading || sending.value) {
    ElMessage.warning("AI回复中，无法新建对话");
    return;
  }

  try {
    const res = await addConversations({
      title: "新会话",
      userId: defaultUserId
    });
    ElMessage.success("新建会话成功");

    // 先刷新会话列表
    await loadConversations();

    // 取最新的第一条会话id，保证和UI一致
    const newId =
      conversationList.value.length > 0
        ? conversationList.value[0].conversationId
        : null;

    if (newId) {
      activeConversationId.value = newId;
      messageList.value = [];
    }
  } catch (error) {
    ElMessage.error("新建会话失败");
  }
}


async function handleSelectConversation(id) {
  // 若当前有消息还在 loading 中（即 AI 正在回复）
  const aiLoading = messageList.value.some(
    msg => msg.role === 0 && msg.loading
  );
  if (aiLoading || sending.value) {
    ElMessage.warning("AI回复中，无法切换对话");
    return;
  }

  // 允许切换会话
  activeConversationId.value = parseInt(id);
  await loadMessages(activeConversationId.value, 1, true);
}

watch(
  messageList,
  async () => {
    await scrollToBottom();
  },
  { deep: true }
);

// 重点修改：支持流式 SSE 片段输出
async function handleSendMessage() {
  if (!newMessage.value.trim() || sending.value) return;
  sending.value = true;

  const content = newMessage.value.trim();
  const userMsg = {
    role: 1,
    content,
    createdAt: new Date()
  };

  try {
    // 1. 发送用户消息（写入数据库）
    await addMessages({
      conversationId: activeConversationId.value,
      role: 1,
      content
    });

    // 2. 本地追加用户消息
    messageList.value.push(userMsg);
    await scrollToBottom();
    newMessage.value = "";

    // 3. 判断当前会话标题是否为默认标题（比如“新会话”）
    const currentConversation = conversationList.value.find(
      c => c.conversationId === activeConversationId.value
    );

    if (
      currentConversation &&
      (currentConversation.title === "新会话" || !currentConversation.title)
    ) {
      // 取用户消息前10个字符作为新标题
      const newTitle = content.length > 10 ? content.slice(0, 10) : content;
      try {
        await updateConversations({
          conversationId: activeConversationId.value,
          title: newTitle
        });
        // 重新加载会话列表，确保左侧标题同步更新
        await loadConversations();
      } catch (error) {
        console.error("更新会话标题失败", error);
      }
    }

    // 4. 初始化 AI 消息占位，用 reactive 保证响应式
    const aiMsg = reactive({
      role: 0,
      content: "",
      createdAt: new Date(),
      loading: true // 只给当前这条设置加载中
    });
    messageList.value.push(aiMsg);
    const aiMsgIndex = messageList.value.length - 1;
    let aiMessageId = null;
    let aiContent = "";
    let isFirstChunk = true;

    const response = await fetch("/dev-api/api/ai/sse/chat", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: "Bearer " + getToken()
      },
      body: JSON.stringify({
        question: content,
        conversationId: activeConversationId.value
      })
    });

    if (!response.ok) throw new Error("请求失败：" + response.statusText);

    const reader = response.body.getReader();
    const decoder = new TextDecoder("utf-8");
    let done = false;

    while (!done) {
      const { value, done: doneReading } = await reader.read();
      done = doneReading;
      if (value) {
        const chunk = decoder.decode(value, { stream: true });
        const lines = chunk.split("\n");

        for (const line of lines) {
          if (line.startsWith("data:")) {
            const dataStr = line.slice(5).trim();
            if (dataStr === "[DONE]") {
              done = true;
              break;
            }
            try {
              const dataObj = JSON.parse(dataStr);
              const delta = dataObj.choices?.[0]?.delta?.content || "";
              const finishReason = dataObj.choices?.[0]?.finish_reason;

              if (delta) {
                aiContent += delta;

                // 实时更新视图：这里用响应式方式更新 messageList
                messageList.value[aiMsgIndex].content = aiContent;
                await scrollToBottom();
              }

              if (finishReason === "stop") {
                done = true;
                messageList.value[aiMsgIndex].loading = false;

                // 只在结束时将完整内容添加到数据库
                try {
                  const addRes = await addMessages({
                    conversationId: activeConversationId.value,
                    role: 0,
                    content: aiContent
                  });
                } catch (err) {
                  console.error("[写入数据库失败]", err);
                }

                break;
              }
            } catch (e) {
              console.warn("SSE解析错误", e, dataStr);
            }
          }
        }
      }
    }
  } catch (error) {
    ElMessage.error("发送失败：" + (error.message || error));
  } finally {
    sending.value = false;
  }
}
</script>

<style scoped>
.app-container {
  padding: 20px;
  height: calc(100vh - 80px);
  box-sizing: border-box;
}

.conversation-sidebar {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.conversation-header {
  font-weight: bold;
  color: #666;
  margin: 8px 0;
}

.conversation-scroll {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  border: 1px solid #e5e5e5;
  border-radius: 4px;
  min-height: 0;
}

.chat-area {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.message-list {
  flex: 1;
  overflow-y: auto;
  border: 1px solid #ddd;
  padding: 12px;
  margin-bottom: 12px;
  min-height: 400px;
}

.message-wrapper {
  display: flex;
  margin-bottom: 10px;
}

.user-message {
  justify-content: flex-end;
}

.ai-message {
  justify-content: flex-start;
}

.message-bubble {
  padding: 10px 14px;
  border-radius: 12px;
  max-width: 90%;
  word-break: break-word;
}

.user-message .message-bubble {
  background-color: #f2f2f2;
  max-width: 50%;
  text-align: left;
}

.ai-message .message-bubble {
  background-color: transparent;
  max-width: 90%;
  text-align: left;
  border: 1px solid #dcdcdc;
}

.message-input {
  width: 100%;
}

.el-menu-item.is-active {
  background-color: #f5f7fa !important;
  font-weight: bold;
  color: #303133;
}

.el-menu-item {
  color: #606266;
}

.el-menu-item:not(.is-active):hover {
  background-color: #f0f2f5;
}

.el-dropdown-link {
  cursor: pointer;
  padding-left: 8px;
  color: #999;
}

.el-menu-item:hover .el-dropdown-link {
  color: #409eff;
}

.el-menu.conversation-menu {
  height: auto !important;
  max-height: none !important;
  overflow: visible !important;
  display: block !important;
}

.conversation-item-content {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  overflow: hidden;
}

.conversation-title {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dropdown-button {
  margin-left: 8px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
}

.chat-area {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.message-list {
  flex: 1;
  overflow-y: auto;
  border: 1px solid #ddd;
  padding: 12px;
  min-height: 0;
}

.message-input-wrapper {
  display: flex;
  padding-top: 12px;
  border-top: 1px solid #eee;
}

.message-input {
  flex: 1;
  margin-right: 12px;
}

.send-button {
  align-self: flex-start;
  height: 54px;
}

.loading-dots {
  margin-left: 8px;
  color: #999;
  font-style: italic;
  animation: blink 1.4s infinite;
}
@keyframes blink {
  0%,
  20% {
    opacity: 0;
  }
  50% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

.loading-wrapper {
  display: inline-flex;
  align-items: center;
  margin-left: 8px;
  color: #999;
  font-style: italic;
}

.loading-dot {
  width: 8px;
  height: 8px;
  margin-left: 6px;
  border-radius: 50%;
  background-color: #409eff; /* Element Plus 蓝色 */
  animation: loading-dot-bounce 1.2s infinite ease-in-out;
}

@keyframes loading-dot-bounce {
  0%,
  100% {
    transform: translateY(0);
    opacity: 1;
  }
  50% {
    transform: translateY(-6px);
    opacity: 0.5;
  }
}

.voice-button {
  margin-left: 8px;
  height: 54px;
}

.message-wrapper {
  display: flex;
  align-items: flex-start;
  margin-bottom: 12px;
}

.user-message {
  display: flex;
  flex-direction: row-reverse; /* 头像在右边 */
  justify-content: flex-start; /* 内容靠右排列 */
  align-items: flex-start;
  margin-bottom: 12px;
}

.user-message .message-avatar {
  margin-left: 12px; /* 头像和气泡间距 */
  margin-right: 0;
  background-color: #409eff;
  color: #fff;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 18px;
  flex-shrink: 0;
  user-select: none;
}

.message-avatar {
  width: 38px;
  height: 38px;
  background-color: #eee;
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 18px;
  flex-shrink: 0;
  user-select: none;
  margin-right: 12px;
  color: #666;
}

.message-bubble {
  background-color: #f9f9f9;
  border-radius: 12px;
  padding: 10px 14px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
  max-width: 70%;
  word-break: break-word;
  line-height: 1.6;
  font-size: 14px;
  white-space: pre-wrap;
}

.user-message .message-bubble {
  background-color: #d7ebff;
  max-width: 70%;
  border-radius: 12px;
  padding: 10px 14px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
  word-break: break-word;
  line-height: 1.6;
  font-size: 14px;
  text-align: left;
  align-self: flex-end; /* 右侧对齐 */
}

.message-time {
  display: block;
  color: #999;
  font-size: 12px;
  margin-top: 4px;
}

</style>